#pragma once

#include "Log.h"
#include "Common.h"

#include "Connection.h"
#include "Socket.h"
#include "Channel.h"
#include "Reactor.h"

namespace zmh
{
    class Listen : public Connection
    {
    public:
        Listen(const Intaddr &_add, int backlog = 8)
            : _listensock(std::make_unique<TcpSocket>())
        {
            // 构建一个监听套接字
            _listensock->GetListenSocket(_add, backlog);
            // 设置关心事件---读事件关心 + ET模式
            SetEvents(EPOLLIN | EPOLLET);
            // 将_linstensock对应的fd设置为非阻塞
            SetFdNonBlock(_listensock->sockfd());
        }
        virtual void Recv() override
        {
            while (true)
            {
                Intaddr peer;
                int sockfd = _listensock->accept(peer);
                if (sockfd >= 0)
                {
                    LOG(LogLevel::INFO) << "有新连接到来:" << peer.Name() << "," << sockfd;

                    // 构建并插入Channel对象
                    Owner()->AddConnection(std::make_unique<zmh::Channel>(sockfd, peer));
                }
                else
                {
                    if (errno == EAGAIN || errno == EWOULDBLOCK) // 无数据
                        break;
                    else if (errno == EINTR) // 信号中断
                        continue;
                    else // 错误发生
                    {
                        Except();
                        return;
                    }
                }
            }
        }
        virtual void Send() override {}
        virtual void Except()
        {
            // 1.获取有问题的fd
            int fd = GetFd();
            // 2.从管理者中移除该连接
            Owner()->DelConnection(fd);
        }
        virtual int GetFd() override { return _listensock->sockfd(); }

    private:
        std::unique_ptr<Socket> _listensock;
    };
}